<!-- 商品管理 -->
<template>
  <div class="app-container">
    <div class="filter-container">
      <div>

        <el-input
        v-model="listQuery.Search"
        placeholder="名称"
        style="width: 200px;"
        class="filter-item"
        clearable
        @clear="handleFilter"
        @keyup.enter.native="handleFilter"
      />
      <el-input
        v-model="listQuery.BarCode"
        placeholder="条码"
        style="width: 200px;"
        class="filter-item"
        clearable
        @clear="handleFilter"
        @keyup.enter.native="handleFilter"
      />
      <!-- <el-select
        v-model="listQuery.SupermarketIDs"
        class="filter-item"
        placeholder="超市名称"
        size="middle"
        filterable
        multiple
        style="width: 240px"
      >
        <el-option
          v-for="item in supermarketSelectOptions"
          :key="item.ID"
          :label="item.Name"
          :value="item.ID"
        />
      </el-select> -->

      <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
        点击搜索
      </el-button>

      <el-button type="primary" icon="el-icon-plus" class="filter-item" @click="handleAdd">新增商品</el-button>
      <el-button type="primary" icon="el-icon-bottom" class="filter-item" @click="handleImport">导入商品</el-button>
      <el-button type="warning" icon="el-icon-edit" class="filter-item"
        :disabled="multiSelected.length === 0"
        @click="handleBatchEditCategory"
>批量修改分类/分线</el-button>
      </div>
      <div>
        <el-checkbox v-model="listQuery.OnlyUncategorized" size="large"
        border label="只查看未分类的" @change="handleUncategorizedChange"
/>
      </div>
    </div>

    <el-table v-loading="listLoading" :data="listData.Items"
      row-key="ID"
      style="width: 100%;margin-top:30px;" border
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange"
>
      <el-table-column type="selection" :selectable="tableSelectable" width="55" />
      <el-table-column align="center" label="ID" width="100">
        <template slot-scope="scope">
          {{ scope.row.ID }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="条码" width="150">
        <template slot-scope="scope">
          {{ scope.row.BarCode }}
        </template>
      </el-table-column>
      <el-table-column align="header-center" label="商品名称" sortable="custom" prop="Name">
        <template slot-scope="scope">
          {{ scope.row.Name }}
        </template>
      </el-table-column>
      <!-- <el-table-column align="center" label="厂价(元)" width="120" sortable="custom" prop="FactoryPrice"> -->
      <el-table-column align="center" label="厂价(元)" width="120">
        <template slot-scope="scope">
          {{ scope.row.FactoryPrice }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="箱规" width="100">
        <template slot-scope="scope">
          {{ scope.row.BoxRule }}
        </template>
      </el-table-column>
      <el-table-column align="header-center" label="分类">
        <template slot-scope="scope">
          {{ scope.row.CategoryDisplay }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="操作">
        <template slot-scope="scope">
          <el-button type="primary" size="small" icon="el-icon-edit" @click="handleEdit(scope)">编辑</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="listData.Total > 0"
      :total="listData.Total"
      :page.sync="listQuery.Page"
      :limit.sync="listQuery.PageSize"
      :page-sizes="[10, 20, 50, 100,200,500]"
      @pagination="getListData"
    />

    <el-dialog :visible.sync="dialogVisible"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
      :title="dialogType === 'edit' ? '编辑商品' : '新增商品'"
>
      <el-form :model="oneData" label-width="80px" label-position="left">
        <el-form-item label="条码">
          <el-input
            v-model="oneData.BarCode"
            placeholder="条码(13位)"
            maxlength="13"
            minlength="13"
/>
        </el-form-item>
        <el-form-item label="名称">
          <el-input
            v-model="oneData.Name"
            placeholder="名称"
            maxlength="60"
            minlength="1"
/>
        </el-form-item>

        <el-form-item label="厂价">
          <el-input-number v-model="oneData.FactoryPrice"
            placeholder="厂价(元)"
            :precision="2"
            :step="0.01"
            :min="0.01"
            :max="99.99"
/>
          </el-form-item>
        <el-form-item label="箱规">
          <el-input-number v-model="oneData.BoxRule"
            placeholder="箱规"
            :precision="0"
            :step="1"
            :min="1"
            :max="999"
/>
        </el-form-item>

        <el-form-item label="分类">
          <el-cascader
            v-model="oneData.CategoryID"
            :options="categoryCascaderOptions"
            :props="{ expandTrigger: 'hover' }"
            clearable
            filterable
            placeholder="分类(可输入搜索)"
            @change="handleCategoryCascaderChange"
>
            <template #default="{ node, data }">
              <span>{{ data.label }}</span>
              <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
            </template>
          </el-cascader>
        </el-form-item>
      </el-form>
      <div style="text-align:right;">
        <el-button type="danger" @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmEdit">确定</el-button>
      </div>
    </el-dialog>

    <el-dialog :visible.sync="importDialogVisible"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
      :title="importDialogVisible ? '导入商品' : '新增商品'"
>

    <upload-excel-component :on-success="importHandleSuccess" :before-upload="beforeUpload"
      :allow-columns="importAllowColumns"
      />
    <div v-show="importExcelData.length" style="margin-top: 20px; line-height: 20px;">
      <span style="font-weight: bold;">导入数据预览</span><br>
      <span>第一个工作表名: {{ importFirstSheetName }}</span><br>
      <span>总条数: {{ importExcelData.length }}</span>
    </div>
    <el-table :data="importExcelData" border highlight-current-row style="width: 100%;margin-top:20px;" height="250">
      <el-table-column v-for="item of importTableHeader" :key="item" :prop="item" :label="item" />
    </el-table>
    <div v-if="importExcelData.length" style="margin-top: 20px;text-align: right;">
      <el-button type="danger" @click="cancelImport">取消</el-button>
      <el-button type="primary" @click="confirmImport">确认导入</el-button>
    </div>
    </el-dialog>

    <!-- 批量修改分类弹窗 -->
    <el-dialog title="批量修改分类" :visible.sync="batchEditCategoryVisible" width="40%">
      <div style="padding: 20px 0;">
        <div style="margin-bottom: 20px;">
          <span style="font-weight: bold;">已选择 {{ multiSelected.length }} 个商品</span>
        </div>

        <!-- 商品列表，限制高度并添加滚动条 -->
        <div v-if="multiSelected.length > 0" style="max-height: 150px; overflow-y: auto; border: 1px solid #ebeef5; border-radius: 4px; padding: 10px; margin-bottom: 20px; background-color: #fafafa;">
          <div v-for="(item, index) in multiSelected" :key="item.ID" style="padding: 5px 0; border-bottom: 1px solid #eee;" :class="{ 'no-border': index === multiSelected.length - 1 }">
            <span style="margin-right: 10px; font-weight: 500;">{{ item.BarCode }}</span>
            <span>{{ item.Name }}</span>
          </div>
        </div>
        <el-cascader
          v-model="selectedCategoryIds"
          :options="categoryCascaderOptions"
          placeholder="请选择分类"
          style="width: 100%;"
          clearable
          @change="handleCategoryChange"
        />
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancelBatchEditCategory">取消</el-button>
        <el-button type="primary" @click="confirmBatchEditCategory">确定</el-button>
      </div>
    </el-dialog>

  </div>
</template>

<script>
import { deepClone } from '@/utils'
import * as supermarket_data_dict from '@/dict/supermarket'
import * as category_data_api from '@/api/warehouse/category'
import * as data_api from '@/api/warehouse/goods'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination

import UploadExcelComponent from '@/components/UploadExcel/index.vue'

const defaultData = {
  BarCode: '', // 条码13位条码号
  Name: '', // 商品名称60个字符以内
  FactoryPrice: 0, // 厂价, 最大99.99
  BoxRule: 1, // 最大999整数
  CategoryID: [], // 商品分类ID
}

export default {
  components: { Pagination, UploadExcelComponent },
  data() {
    return {
      listData: {
        Items: [],
        Total: 0
      },
      listLoading: false,
      listQuery: {
        Page: 1,
        PageSize: 10,

        BarCode: '',
        Search: '',
        ClassID: 0,
        LevelID: 0,
        BrandID: 0,
        OnlyUncategorized: false,

        Sorts: 'updated_at DESC',
      },
      oneData: Object.assign({}, defaultData),
      dialogVisible: false,
      dialogType: 'new',

      // Ref: https://element-plus.org/en-US/component/cascader.html#basic-usage
      categoryCascaderOptions: [
        {
          value: 0,
          label: '请选择分类',
          children: [
            // {value, label, children...}
          ]
        }
      ],

      classOptions: [],
      levelOptions: [],
      brandOptions: [],

      multiSelected: [], // 已批量选中的行的数据

      // 导入excel相关
      importDialogVisible: false,
      importExcelData: [],
      importTableHeader: [],
      importFirstSheetName: '',
      // 条码	商品名称	厂价	箱规
      importAllowColumns: [
        '条码',
        '商品名称',
        '厂价',
        '箱规'
      ],

      // 批量修改分类相关
      batchEditCategoryVisible: false,
      selectedCategoryIds: []
    }
  },
  computed: {
  },
  watch: {
    dialogVisible(newVal) {
      if (newVal) {
        this.fetchCategoryCascaderOptions() // 每次变为可见时重新加载下拉列表数据
      }
    }
  },
  mounted() {
    this.fetchCategoryCascaderOptions()
  },
  /**
   * 生命周期钩子函数 - 创建实例后调用
   *
   * 调用getListData方法以获取列表数据
   */
  created() {
    this.getListData()
  },
  methods: {
    tableSelectable() {
      return true
    },
    handleUncategorizedChange() {
      this.getListData()
    },

    getListData() {
      this.listLoading = true
      // 确保查询参数与复选框状态同步
      // this.listQuery.OnlyUncategorized = this.onlyUncategorized
      data_api.list(this.listQuery).then(res => {
        this.listData = res.data
        this.normalizeData()
        this.listLoading = false
      }).catch(() => {
        this.listLoading = false
      })
    },

    normalizeData() {
      this.listData?.Items.forEach(item => {
        item.CategoryDisplay = item.Category?.ID === -1 ? '未分类' : [item.Category.ClassName, item.Category.LevelName, item.Category.BrandName].join(' / ')
      })
    },

    handleFilter() {
      this.listQuery.Page = 1
      this.getListData()
    },

    async confirmEdit() {
      const isEdit = this.dialogType === 'edit'

      if (!isEdit) {
        await data_api.create(this.oneData)
        this.dialogVisible = false
        this.$message({
          type: 'success',
          message: `新增商品: ${this.oneData.Name} 成功`
        })
      } else {
        await data_api.update(this.oneData)
        this.dialogVisible = false
        this.$message({
          type: 'success',
          message: `更新商品: ${this.oneData.Name} 成功`
        })
      }
      this.getListData()
    },
    handleAdd() {
      this.oneData = Object.assign({}, defaultData)
      this.oneData.name
      this.dialogType = 'new'
      this.dialogVisible = true
    },

    handleImport() {
      this.importDialogVisible = true
      this.importExcelData = []
      this.importTableHeader = []
    },

    beforeUpload(file) {
      const MaxSize = 1024 * 1024 * 100
      const sizeLimited = file.size > MaxSize

      if (!sizeLimited) {
        return true
      }

      const m = MaxSize / 1024 / 1024
      this.$message({
        message: `Please do not upload files larger than ${m}M in size.`,
        type: 'warning'
      })
      return false
    },
    importHandleSuccess({ results, header, firstSheetName }) {

      this.importExcelData = results
      this.importTableHeader = header
      this.importFirstSheetName = firstSheetName
    },

    cancelImport() {
      this.importDialogVisible = false
      this.importExcelData = []
      this.importTableHeader = []
      this.importFirstSheetName = ''
    },

    confirmImport() {
      const results = this.importExcelData

      // check results
      if (!results || !results.length) {
        this.$message({
          message: 'No data imported',
          type: 'warning'
        })
        return
      }

      const formatedResults = []
      for (let i = 0; i < results.length; i++) {
        const result = results[i]
        if (!result) {
          continue
        }

        const r = {}
        // 把中文变量/属性换成英文的
        r.BarCode = result.条码 + ''
        r.Name = result.商品名称
        r.FactoryPrice = result.厂价
        r.BoxRule = result.箱规
        if (!r.BarCode) {
          this.$message({
            message: `条码不能为空: ${JSON.stringify(r)}`,
            type: 'warning'
          })
          return
        }
        if (!r.Name) {
          this.$message({
            message: `商品名称不能为空: ${JSON.stringify(r)}`,
            type: 'warning'
          })
          return
        }
        if (!r.FactoryPrice) {
          this.$message({
            message: `厂价不能为空: ${JSON.stringify(r)}`,
            type: 'warning'
          })
          return
        } else {
          r.FactoryPrice = parseFloat(r.FactoryPrice)
        }
        if (!r.BoxRule) {
          this.$message({
            message: `箱规不能为空: ${JSON.stringify(r)}`,
            type: 'warning'
          })
          return
        } else {
          r.BoxRule = parseInt(r.BoxRule)
        }

        formatedResults.push(r)
      }

      // console.log(formatedResults)
      data_api.import_(formatedResults).then(res => {
        const data = res.data

        this.$message({
          type: 'success',
          dangerouslyUseHTMLString: true,
          message: `导入商品数据完成, 详情:<br>成功数: ${data.SuccessCount}<br>失败数: ${data.FailedCount}<br>条码已存在(覆盖)数: ${data.ExistedCount}`
        })

        this.importDialogVisible = false
        this.getListData()
      }).catch(() => {
        this.$message({
          type: 'error',
          mettage: `导入商品数据失败`
        })
      })
    },

    handleEdit(scope) {
      this.dialogType = 'edit'
      this.dialogVisible = true
      this.oneData = deepClone(scope.row, ['Category', 'CreatedAt', 'UpdatedAt'])
      this.oneData.CategoryID = [scope.row.Category.ClassID, scope.row.Category.LevelID, scope.row.Category.BrandID]
    },

    async fetchCategoryCascaderOptions() {
      const res = await category_data_api.list({
        Page: 1,
        PageSize: -1, // no limit
      })
      const items = (res?.data.Items)

      // 组织成三级嵌套结构
      const options = []

      // 第一级：按 ClassID 分组
      const classMap = new Map()

      items.forEach(item => {
        // 处理 Class 层级
        if (!classMap.has(item.ClassID)) {
          classMap.set(item.ClassID, {
            value: item.ClassID, // 使用 ClassID 作为 value
            label: item.ClassName || `Class ${item.ClassID}`, // 使用 ClassName 作为 label
            children: new Map() // 使用 Map 存储 Level 层级
          })
        }
        const classItem = classMap.get(item.ClassID)

        // 处理 Level 层级
        if (!classItem.children.has(item.LevelID)) {
          classItem.children.set(item.LevelID, {
            value: item.LevelID, // 使用 LevelID 作为 value
            label: item.LevelName || `Level ${item.LevelID}`, // 使用 LevelName 作为 label
            children: [] // 数组存储 Brand 层级
          })
        }
        const levelItem = classItem.children.get(item.LevelID)

        // 处理 Brand 层级
        levelItem.children.push({
          value: item.BrandID, // 使用 BrandID 作为 value
          label: item.BrandName || `Brand ${item.BrandID}` // 使用 BrandName 作为 label
        })
      })

      // 将 Map 转换为数组格式
      classMap.forEach(classItem => {
        const levelChildren = []
        classItem.children.forEach(levelItem => {
          levelChildren.push(levelItem)
        })

        options.push({
          value: classItem.value,
          label: classItem.label,
          children: levelChildren
        })
      })

      // console.log(JSON.stringify(options, null, 2));
      this.categoryCascaderOptions = options
    },
    handleCategoryCascaderChange(value) {
      // console.log(value)
    },
    handleCategoryChange(value) {
      // 分类选择变化时的回调，可以在这里添加额外的处理逻辑
    },
    handleSelectionChange(val) {
      this.multiSelected = val
    },
    handleBatchEditCategory() {
      this.selectedCategoryIds = []
      this.batchEditCategoryVisible = true
    },

    async confirmBatchEditCategory() {
      if (!this.selectedCategoryIds || this.selectedCategoryIds.length === 0) {
        this.$message({
          message: '请选择分类',
          type: 'warning'
        })
        return
      }

      const goodsIds = this.multiSelected.map(item => item.ID)

      try {
        const result = await data_api.batchUpdate({
          GoodsIDs: goodsIds,
          CategoryID: this.selectedCategoryIds
        })
        // 显示成功和失败的数量
        this.$message({
          message: `批量修改分类完成，成功 ${result.data.SuccessCount} 个，失败 ${result.data.FailedCount} 个`,
          type: 'success'
        })

        this.batchEditCategoryVisible = false
        this.getListData() // 重新获取列表数据
      } catch (error) {
        this.$message({
          message: '批量修改分类失败',
          type: 'error'
        })
      }
    },

    cancelBatchEditCategory() {
      this.batchEditCategoryVisible = false
      this.selectedCategoryIds = []
    },

    // 处理表格排序
    handleSortChange({ prop, order }) {
      const sorts = []
      if (prop === 'FactoryPrice') {
        if (order === 'ascending') {
          sorts.push('g.factory_price ASC')
        } else if (order === 'descending') {
          sorts.push('g.factory_price DESC')
        }
        sorts.push(' g.updated_at DESC')
      } else if (prop === 'Name') {
        if (order === 'ascending') {
          sorts.push('g.name ASC')
        } else if (order === 'descending') {
          sorts.push('g.name DESC')
        }
        sorts.push(' g.updated_at DESC')
      }
      this.listQuery.Sorts = sorts.join(', ')
      this.getListData() // 重新加载数据
    }
  }
}
</script>

  <style lang="scss" scoped>
  .app-container {
    .roles-table {
      margin-top: 30px;
    }
  }

  .no-border {
    border-bottom: none !important;
  }
</style>
